package com.global.college.api;


import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.global.college.UserData;
import com.global.college.data.net.CourseDetailBean;
import com.global.college.data.net.CourseVideosBean;
import com.global.college.data.net.HomeGoodListBean;
import com.global.college.data.net.MyCourseListBean;
import com.global.college.data.net.MyTrainListBean;
import com.global.college.data.net.TagListBean;
import com.global.college.data.net.TrainBannerBean;
import com.global.college.data.net.TrainDetailBean;
import com.global.college.data.net.TrainStageBean;
import com.global.college.data.net.VersionBean;
import com.global.college.data.net.VideoDetailBean;
import com.global.college.data.net.VideoHistoryBean;
import com.global.college.ui.bean.GoodsDetailModel;
import com.global.college.ui.bean.MyOrderDetail;
import com.global.college.ui.bean.MyOrderListModel;
import com.global.college.ui.bean.OrderCreateModel;
import com.global.college.ui.bean.TokenModel;
import com.global.college.ui.bean.requestBean.CallBackModel;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import rx.Observable;
import rx.android.BuildConfig;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by fu on 2020/2/16.
 * Describe: 客户端请求
 */
@SuppressWarnings("unchecked")
public class RequestClient {

    private final static String TAG = "RequestClient";

    /**
     * 超时时间(秒)
     */
    public static final int DEFAULT_TIMEOUT = 1800;

    public static Observable.Transformer IO_UI = new ClassicIOTransformer();
    /**
     * 单例
     */
    private static RequestClient requestClient;

    private static HttpLoggingInterceptor BODY_LOGGER = new HttpLoggingInterceptor();
    private static HttpLoggingInterceptor BASIC_LOGGER = new HttpLoggingInterceptor();

    private Retrofit mRetrofit;

    private ServerAPI serverApi;
    private String app = "app";


    public void setDebug() {
        if (BuildConfig.DEBUG) {
            BODY_LOGGER.setLevel(HttpLoggingInterceptor.Level.BODY);
            BASIC_LOGGER.setLevel(HttpLoggingInterceptor.Level.BASIC);
        } else {
            BODY_LOGGER.setLevel(HttpLoggingInterceptor.Level.NONE);
            BASIC_LOGGER.setLevel(HttpLoggingInterceptor.Level.NONE);
        }
    }

    private RequestClient() {
        //系统平台版本号
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        builder.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);//超时时间
        builder.readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS);//上传超时时间
        builder.retryOnConnectionFailure(true);//启用自动重连
        //拦截器－添加公共字段
        //builder.addInterceptor(commonInterceptor);
        //builder.addNetworkInterceptor(new LoggingInterceptor());
        builder.addInterceptor(new HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level.BODY));//这是打印所有日志
        builder.addInterceptor(new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request newRequest = chain.request().newBuilder().header("Authorization", UserData.getInstance().getToken()).build();
                return chain.proceed(newRequest);
            }
        });

        setDebug();
        OkHttpClient okHttpClient = builder.build();
        mRetrofit = new Retrofit.Builder()
                .baseUrl(URLs.BASE_URL)
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create())
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                .build();
        serverApi = mRetrofit.create(ServerAPI.class);
    }

    //外部调用
    @SuppressWarnings("unchecked")
    public static RequestClient getInstance() {
        if (null == requestClient) {
            requestClient = new RequestClient();
        }
        return requestClient;
    }

    /* 获取训练营2 获取课程1
     * @return
     */
    public Observable<HomeGoodListBean> getGoodListBean(int goodType, int sortBy, long tagId, int classLevel) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("pageNum", 1);
        jObj.addProperty("pageSize", 100);
        jObj.addProperty("goodType", goodType);
        jObj.addProperty("sortBy", sortBy);
        jObj.addProperty("classSubjectTag", tagId);
        jObj.addProperty("classLevel", classLevel);
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.getGoodList(requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /* 获取训练营2 获取课程1
     * @return
     */
    public Observable<HomeGoodListBean> getGoodListBean(int goodType) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("pageNum", 1);
        jObj.addProperty("pageSize", 100);
        jObj.addProperty("goodType", goodType);
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.getGoodList(requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<TagListBean[]> getTagList() {
        return serverApi.getTagList()
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 训练营详情
     *
     * @param trainId
     * @return
     */
    public Observable<TrainStageBean[]> getTrainList(String trainId) {
        return serverApi.getTrainList(trainId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 训练营顶部banner
     *
     * @param trainId
     * @param userId
     * @return
     */
    public Observable<TrainBannerBean> getTrainBanner(String trainId, String userId) {
        return serverApi.getTrainBanner(trainId, userId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<CourseVideosBean[]> getCourseVideos(String classId) {
        return serverApi.getCourseVideos(classId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<VideoDetailBean> getVideoDetail(String videoId) {
        return serverApi.getVideoDetail(videoId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<TrainDetailBean> getTrainDetail(String trainId, String userId) {
        return serverApi.getTrainDetail(trainId, userId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
    public Observable<CourseDetailBean> getCourseDetail(String goodId) {
        return serverApi.getCourseDetail(goodId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<Object> saveVideoHistory(String userId,String videoId,String trainingId,String classId,int duration) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("userId", userId);
        jObj.addProperty("videoId", videoId);
        jObj.addProperty("trainingId", trainingId);
        jObj.addProperty("classId", classId);
        jObj.addProperty("duration", duration);

        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.saveVideoHistory(requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<VideoHistoryBean> getVideoHistory(String userId, String trainId, String classId) {
        return serverApi.getVideoHistory(userId,trainId,classId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<CourseDetailBean> getMyCourseDetail(String classId) {
        return serverApi.getMyCourseDetail(classId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<VersionBean> getVersionInfo() {
        return serverApi.getVersionInfo("uton:edu:android")
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }



    /**
     * 9.用户订单
     * Authorization
     */
    public Observable<MyOrderListModel> getOrderList(String userId, String orderState, int pageNum, int pageSize) {
        return serverApi.getOrderList(UserData.getInstance().getToken(),userId, orderState,  pageNum,  pageSize)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 10.我的课程 分页列表
     * Authorization
     * pageNum
     * pageSize
     * type	0全部  1学习中  2已完成(int)
     */
    public Observable<MyCourseListBean> getCourseList(int pageNum, int pageSize, int type) {
        return serverApi.getCourseList(UserData.getInstance().getToken(), pageNum, pageSize, type)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 11.我的课程 课程详情
     * Authorization
     * classId	课程id(String)
     */
    public Observable<Object> getCoursesDetail(String classId) {
        return serverApi.getCourseDetail(UserData.getInstance().getToken(), classId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 12.我的训练营 分页列表
     * Authorization
     * pageNum
     * pageSize
     * type	0全部  1学习中  2已完成(int)
     */
    public Observable<MyTrainListBean> getTraningList(int pageNum, int pageSize, int type) {
        return serverApi.getTraningList(UserData.getInstance().getToken(), pageNum, pageSize, type)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 13.我的训练营 训练营详情
     * Authorization
     * trainingId
     */
    public Observable<Object> getTraningDetail(String trainingId) {
        return serverApi.getTraningDetail(UserData.getInstance().getToken(), trainingId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 14.创建订单
     * Authorization
     * userId	用户id
     * goodId	商品id，商品列表获取的一大串字符串那个
     * source	来源
     */
    public Observable<OrderCreateModel> createOrder(String userId, String goodId) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("userId", userId);
        jObj.addProperty("goodId", goodId);
        jObj.addProperty("source", "uton_edu_android");
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.createOrder(UserData.getInstance().getToken(), requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 15.取消订单
     * Authorization
     * orderId	订单ID  一大串字符串那个
     */
    public Observable<Object> cancleOrder(String orderId) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("orderId", orderId);
        jObj.addProperty("source", "uton_edu_android");
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.cancleOrder(UserData.getInstance().getToken(), requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 16.支付回调
     * Authorization
     * paymentType	 支付渠道
     * notifyTime	通知时间
     * businessOrderNo	业务平台订单号
     * paymentTradeNo	支付平台流水号
     * tradeStatus	交易状态
     * totalAmount	订单金额
     * receiptAmount	实际金额
     * subject	标题。由商户定义的
     * gmtCreate	交易创建时间
     * gmtPayment	交易付款时间
     * gmtRefund	交易退款时间
     * gmtClose	交易结束时间
     * passbackParams	回传参数商户定义的
     */
    public Observable<Object> payCallBack(CallBackModel params) {
        String body = new Gson().toJson(params);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.payCallBack(UserData.getInstance().getToken(), requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    /**
     * 17.商品 课程详情
     * Authorization
     * goodId
     */
    public Observable<GoodsDetailModel> getGoodsDetail(String goodId) {
        return serverApi.getGoodsDetail(UserData.getInstance().getToken(), goodId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }
    /**
     * 18.订单详情
     *
     * Authorization
     * orderId
     */
    public Observable<MyOrderDetail> getOrderDetail(String orderId) {
        return serverApi.getOrderDetail(UserData.getInstance().getToken(), orderId)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<TokenModel> getWxToken(String openId, String accessToken) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("WxOpenId", openId);
        jObj.addProperty("Authorization", accessToken);
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.getWxToken(app, UserData.getInstance().getToken(), requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<TokenModel> bindPhone(String openId, String unionId, String phone, String verifyCode, String accessToken) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("WxOpenId", openId);
        jObj.addProperty("WxUnionId", unionId);
        jObj.addProperty("Phone", phone);
        jObj.addProperty("VerifyCode", verifyCode);
        jObj.addProperty("Authorization", accessToken);
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.bindPhone(app, requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<BaseResponseModel> bindWx(String openId, String unionId, String accessToken) {
        JsonObject jObj = new JsonObject();
        jObj.addProperty("WxOpenId", openId);
        jObj.addProperty("WxUnionId", unionId);
        jObj.addProperty("Authorization", accessToken);
        String body = new Gson().toJson(jObj);
        RequestBody requestBody = RequestBody.create(MediaType.parse("application/json"), body);
        return serverApi.bindWx(UserData.getInstance().getToken(), requestBody)
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }

    public Observable<BaseResponseModel> unBindWx() {
        return serverApi.unbindWx(UserData.getInstance().getToken())
                .map(new HttpResultFunc<>())
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread());
    }



}